#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <ogcsys.h>
#include <gccore.h>

#include <stdio.h>

#include <wiiuse/wiiuse.h>
#include <wiiuse/wpad.h>

#include "GRRLIB.h"

#include <ogc/ios.h>
#include <ogc/stm.h>
#include <ogc/ipc.h>

#include "ocl_cards.h"
#include "ocl_video.h"

#include <time.h>
#include <ogc/color.h>

#include "../gfx/pointer.h"
#include "../gfx/bg.h"
#include "../gfx/hold.h"
#include "../gfx/no_hold.h"

#define MAX_WIIMOTES
//#include "../gfx/card_face.h"

//#include "../gfx/spin.h"
//#include "../gfx/sound_on.h"
//#include "../gfx/sound_off.h"
//#include "../gfx/add.h"
//#include "../gfx/decrease.h"

#define FLIP_DELAY 10
#define MAX_BET 5

CARDS_Deck my_deck;

CARDS_Card my_hand[5];
int hold[5];

CARDS_Ptr p_cards;
VIDEO_Ptr p_video;

int loc_x, loc_y;

extern u16 *GRRLIB_buffer;

int hand_index=0;
int draw = 0;
int flip[5];
int credits  = 100;
int add_amount = 0;
int bet=MAX_BET;

CARDS_PokerHandType current_hand_type = NOTHING;
typedef void (*Loader_Entry)(void);
Loader_Entry loader = (Loader_Entry)0x80001800;

void delay(clock_t lMillisec)
{
//clock_t finish;
//finish = clock() + lMillisec;
//while (finish > clock())
//;
}

int init()
{

	GRRLIB_buffer=(u16 *)malloc(640*480*2);	
	
	VIDEO_Init();
	PAD_Init();
	WPAD_Init();
	GRRLIB_InitVideo();
	GRRLIB_Start(640, 480, 80, 60);
	GRRLIB_FillScreen(0x0000);		
	GRRLIB_Render();
	VIDEO_WaitVSync();

        printf("VIDEO Initialized...\n");	

        if(OCL_VIDEO_Init(&p_video, 640, 480)!=0)
        {
        	printf("Failed OCL_VIDEO_INIT!\n");
		return 1;
	}
	else
	{
        	printf("OCL_VIDEO Initialized...\n");	
	}

	int i=0;
	for(;i<5;i++) flip[i] = 0;

        if(CARDS_Init(&p_cards)!=0)
	{
		printf("Failed to init CARDS!\n");
		OCL_VIDEO_Destruct(&p_video);
		return 1;
	}
        printf("CARDS Initialized...\n");	

	if(CARDS_InitSound(&p_cards)!=0)
	{
		printf("Failed to init CARDS_Sound!\n");
		return 1;
	}

	return 0;
}

void RenderMenu()
{
	int i = 0;
	char str_buf[100];
	int off = 60;
	VIDEO_Flush();
	VIDEO_WaitVSync();

	GRRLIB_FillScreen(BLUE);		

	OCL_VIDEO_RenderText(&p_video, "Video Poker v0.1 [By BeardFace]", 12, 100, 10,WHITE,BLUE);

	OCL_VIDEO_RenderText(&p_video, "Controls:", 12, 30, 25+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "New Game (Draw): <B>", 12, 50, 40+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Hold Card:       <A>,<UP>,<DOWN>", 12, 50, 55+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Select Card:     <LEFT>,<RIGHT>", 12, 50, 70+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Change Bet:      <+>,<->|<X>,<Y>", 12, 50, 85+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Enable/Disable Sound:  <1>|<Z>", 12, 50, 100+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Show Menu:       <Home>|<Start>", 12, 50, 115+off,WHITE,BLUE);

	OCL_VIDEO_RenderText(&p_video, "Press <A> to Quit", 12, 40, 142+off,WHITE,BLUE);
	OCL_VIDEO_RenderText(&p_video, "Press <HOME> | <Start> to return to the game.", 12, 40, 162+off,WHITE,BLUE);

	OCL_VIDEO_RenderText(&p_video, "Sound", 13, 50, 377,WHITE,BLUE);
	if(p_cards.SOUND_ENABLED)
	{
		OCL_VIDEO_RenderText(&p_video, "[ON]", 13, 153, 377,WHITE,BLUE);
	}
	else
	{
		OCL_VIDEO_RenderText(&p_video, "[OFF]", 13, 153, 377,WHITE,BLUE);
	}

	OCL_VIDEO_EndFrame(&p_video);
	GRRLIB_Render();	//Render the GRRLIB_buffer to screen
	VIDEO_WaitVSync();	//wait for Vsync
}

void RenderScreen()
{
	int i = 0;
	char str_buf[100];

	VIDEO_Flush();
	VIDEO_WaitVSync();

	OCL_VIDEO_RenderImage(&p_video, &bg_img, bg_width, bg_high, 0, 0);

	for(;i<5;i++)
	{
		if(flip[i] == 0)
		{
			CARDS_RenderCard(&p_cards, &p_video, &my_hand[i], (i+1)*(p_video.SCREEN_WIDTH/6), p_video.SCREEN_HEIGHT/2);
		}
		else
		{
			CARDS_RenderDownCard(&p_cards, &p_video, &my_hand[i], (i+1)*(p_video.SCREEN_WIDTH/6), p_video.SCREEN_HEIGHT/2);	
		}	

		if(draw == 1)
		{
			if(hand_index == i)
			{

				loc_x = (i+1)*(p_video.SCREEN_WIDTH/6)-pointer_width/2;
				loc_y = (p_video.SCREEN_HEIGHT/2)+(174/2)+hold_high;

				OCL_VIDEO_RenderImage(&p_video, &pointer_img, pointer_width, pointer_high, loc_x, loc_y);

			}

			loc_x = (i+1)*(p_video.SCREEN_WIDTH/6)-no_hold_width/2;
			loc_y = (p_video.SCREEN_HEIGHT/2)+(174/2);

			if(hold[i] == 0)
			{

				OCL_VIDEO_RenderImage(&p_video, &no_hold_img, no_hold_width, no_hold_high, loc_x, loc_y);
			}
			else
			{
				OCL_VIDEO_RenderImage(&p_video, &hold_img, hold_width, hold_high, loc_x, loc_y);   
			}
		//draw hold/keep
		}
	}

	OCL_VIDEO_RenderText(&p_video, "Royal Flush             10000:1", 1, 150, 0, BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "Straight Flush           1000:1", 1, 150, 12,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "4 of a Kind               200:1", 1, 150, 24,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "Full House                 25:1", 1, 150, 36,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "Flush                      15:1", 1, 150, 48,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "Straight                   10:1", 1, 150, 60,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "3 of a Kind                 5:1", 1, 150, 72,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "2 Pair                      3:1", 1, 150, 84,BLACK,WHITE);
	OCL_VIDEO_RenderText(&p_video, "1 Pair (Jacks or better)    2:1", 1, 150, 96,BLACK,WHITE);

	OCL_VIDEO_RenderText(&p_video, "Press <Home> | <Start> to bring up the menu.", 1, 50, 378,WHITE,BLUE);

	sprintf(str_buf,"WIN:  %d \0",add_amount);  
	OCL_VIDEO_RenderText(&p_video, str_buf, 2, 50, 400,WHITE,BLUE);
	sprintf(str_buf,"BET:  %d \0",bet);  
	OCL_VIDEO_RenderText(&p_video, str_buf, 2, 270, 400,WHITE,BLUE);
	sprintf(str_buf,"CREDITS:  %d\0",credits);
	OCL_VIDEO_RenderText(&p_video, str_buf, 2, 400, 400,WHITE,BLUE);

	OCL_VIDEO_EndFrame(&p_video);
	GRRLIB_Render();	//Render the GRRLIB_buffer to screen
	VIDEO_WaitVSync();	//wait for Vsync
}

void NewHand()
{
        //Set to get a new deck and shuffle for each hand...
        CARDS_GetNewDeck(&my_deck);
        CARDS_Shuffle(&my_deck);
	add_amount = 0;
        if(credits > bet)
        {
        	credits = credits-bet;
		CARDS_PlayCoinSound(&p_cards);
		delay(FLIP_DELAY*2);
        }

	int i = 0;
	for(;i<5;i++)
	{
		//animate draw
		flip[i] = 1;
		CARDS_PlayFlipSound(&p_cards);
		RenderScreen();
		delay(FLIP_DELAY);

		//draw card
		CARDS_DealCard(&my_deck,&my_hand[i]);
		hold[i] = 0;
	}
	i = 0;
	//animate draw
	for(;i<5;i++)
	{
		flip[i] = 0;
		CARDS_PlayDealSound(&p_cards);
		RenderScreen();
		delay(FLIP_DELAY);
        }
	draw = 1;

	RenderScreen();
}

void AddCredits()
{
	add_amount = 0;
    	//Add Credits and Animate
    	switch(current_hand_type)
    	{
    		case ONE_PAIR_JACKS_OR_BETTER:
			add_amount=2*bet;
			break;
		case TWO_PAIR:
			add_amount=3*bet;
			break;
		case THREE_OF_A_KIND:
			add_amount=5*bet;
			break;
		case STRAIGHT:
			add_amount=10*bet;
			break;
		case FLUSH:
			add_amount=15*bet;
			break;
		case FULL_HOUSE:
			add_amount=25*bet;
			break;
		case FOUR_OF_A_KIND:
			add_amount=200*bet;
			break;
		case STRAIGHT_FLUSH:
			add_amount=1000*bet;
			break;
		case ROYAL_FLUSH:
			add_amount=10000*bet;
			break;
		default:
			break;
	}

	credits = credits+add_amount;

	RenderScreen();		
	if(add_amount > 0)
		CARDS_PlayWinSound(&p_cards);
}

void DrawCards()
{
	int i=0;
	for(;i<5;i++)
	{
		if(hold[i] == 0)
                {
			//logic to animate flipping prior to drawing
			flip[i] = 1;
			CARDS_PlayFlipSound(&p_cards);
			RenderScreen();
			delay(FLIP_DELAY);

			//draw the actual card
			CARDS_DealCard(&my_deck,&my_hand[i]);
                }

	}
	draw = 0;

	//Animate drawing cards for fun
	i=0;

	for(;i<5;i++)
	{
		if(hold[i] == 0)
                {
			flip[i] = 0;
			CARDS_PlayDealSound(&p_cards);
			RenderScreen();
			delay(FLIP_DELAY);
                }
	}


	RenderScreen();
}

int main(int argc, char **argv)
{
		
	//int done=0;

	int in_hand=0;
	int in_menu=0;

	if(init()!=0) return 1;
	//CARDS_PlayCasinoSound(&p_cards);
	NewHand();

	while(1) 
	{
		VIDEO_WaitVSync();

		PAD_ScanPads ();
		WPAD_ScanPads();


		if (PAD_ButtonsDown(0) & PAD_BUTTON_START || WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
		{
			if(in_menu)
			{
				in_menu = 0;
				RenderScreen();
			}
			else
			{
				in_menu = 1;
				RenderMenu();
			}
		}
		else if((PAD_ButtonsDown(0) & PAD_BUTTON_DOWN) ||(PAD_ButtonsDown(0) & PAD_BUTTON_UP) ||(PAD_ButtonsDown(0) & PAD_BUTTON_A) || WPAD_ButtonsDown(0) & WPAD_BUTTON_A || WPAD_ButtonsDown(0) & WPAD_BUTTON_UP  || WPAD_ButtonsDown(0) & WPAD_BUTTON_DOWN)
		{
			if(in_menu &&  ((WPAD_ButtonsDown(0) & WPAD_BUTTON_A) || (PAD_ButtonsDown(0) & PAD_BUTTON_A)))
			{
				//TODO Show Poker Menu (For now, exit...);
				CARDS_Destruct(&p_cards);
			        OCL_VIDEO_Destruct(&p_video);
				loader();
			}
			else if(!in_menu)
			{
				if(draw)
				{
					hold[hand_index]=(!hold[hand_index]);
					CARDS_PlayPushSound(&p_cards);
					RenderScreen();
				}
				else
				{
					NewHand();
					current_hand_type = NOTHING;
				}
			}
		}
		else if((PAD_ButtonsDown(0) & PAD_BUTTON_LEFT) || (PAD_ButtonsDown(0) & PAD_TRIGGER_L)  || WPAD_ButtonsDown(0) & WPAD_BUTTON_LEFT)
		{
			if(!in_menu)
			{
				if(hand_index > 0) hand_index--;
				RenderScreen();
			}
		}
		else if((PAD_ButtonsDown(0) & PAD_BUTTON_RIGHT) || (PAD_ButtonsDown(0) & PAD_TRIGGER_R) || WPAD_ButtonsDown(0) & WPAD_BUTTON_RIGHT)
		{
			if(!in_menu)
			{
				if(hand_index < 4) hand_index++;
				RenderScreen();
			}
		}
		else if(PAD_ButtonsDown(0) & PAD_BUTTON_X || WPAD_ButtonsDown(0) & WPAD_BUTTON_MINUS)
		{
			if(!in_menu)
				if(!draw)
				{
					if(bet > 1){bet--;}
					RenderScreen();
				}
		}
		else if(PAD_ButtonsDown(0) & PAD_BUTTON_Y || WPAD_ButtonsDown(0) & WPAD_BUTTON_PLUS)
		{
			if(!in_menu)
				if(!draw)
				{
					if(bet < MAX_BET){bet++;}
					RenderScreen();
				}
		}
		else if((PAD_ButtonsDown(0) & PAD_TRIGGER_Z) || WPAD_ButtonsDown(0) & WPAD_BUTTON_1)
		{
			p_cards.SOUND_ENABLED = (!(p_cards.SOUND_ENABLED));
			if(in_menu)
			{
				RenderMenu();
			}
			else
			{
				RenderScreen();
			}
		}
		else if((PAD_ButtonsDown(0) & PAD_BUTTON_B  || WPAD_ButtonsDown(0) & WPAD_BUTTON_B))
		{
			if(!in_menu)
			{
				//deal cards not held (if draw is true)
				if(draw)
				{
					DrawCards();
					current_hand_type = CARDS_GetPokerHandType(my_hand, 5, 5);
					AddCredits();
				}
				else
				{
					NewHand();
					current_hand_type = NOTHING;
				}
			}
		}
		
	}

			/* WiiMote support later...
				case SDL_MOUSEBUTTONDOWN:
				for(i=0;i<5;i++)
				{
					if(CARDS_IsCardClicked(my_hand[i],event.button.x,event.button.y))
					{
						hand_index=i;
						hold[hand_index]=(!hold[hand_index]);
						CARDS_PlayPushSound(&p_cards);
						RenderScreen();
					}
				}
				break;
			*/


	return 0;
}

